package com.moxiao.yfjh.framework.common.util.date;

import cn.hutool.core.date.LocalDateTimeUtil;
import org.apache.commons.lang3.time.DateFormatUtils;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.Calendar;
import java.util.Date;

/**
 * 时间工具类
 *
 * @author mx
 */
public class DateUtils {

    /**
     * 时区 - 默认
     */
    public static final String TIME_ZONE_DEFAULT = "GMT+8";

    /**
     * 秒转换成毫秒
     */
    public static final long SECOND_MILLIS = 1000;

    public static final String FORMAT_YEAR_MONTH_DAY = "yyyy-MM-dd";

    public static final String FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND = "yyyy-MM-dd HH:mm:ss";

    public static final String FORMAT_HOUR_MINUTE_SECOND = "HH:mm:ss";

    /**
     * 将 LocalDateTime 转换成 Date
     *
     * @param date LocalDateTime
     * @return LocalDateTime
     */
    public static Date of(LocalDateTime date) {
        if (date == null) {
            return null;
        }
        // 将此日期时间与时区相结合以创建 ZonedDateTime
        ZonedDateTime zonedDateTime = date.atZone(ZoneId.systemDefault());
        // 本地时间线 LocalDateTime 到即时时间线 Instant 时间戳
        Instant instant = zonedDateTime.toInstant();
        // UTC时间(世界协调时间,UTC + 00:00)转北京(北京,UTC + 8:00)时间
        return Date.from(instant);
    }

    /**
     * 将 Date 转换成 LocalDateTime
     *
     * @param date Date
     * @return LocalDateTime
     */
    public static LocalDateTime of(Date date) {
        if (date == null) {
            return null;
        }
        // 转为时间戳
        Instant instant = date.toInstant();
        // UTC时间(世界协调时间,UTC + 00:00)转北京(北京,UTC + 8:00)时间
        return LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
    }

    public static Date addTime(Duration duration) {
        return new Date(System.currentTimeMillis() + duration.toMillis());
    }

    public static boolean isExpired(Date time) {
        return System.currentTimeMillis() > time.getTime();
    }

    public static boolean isExpired(LocalDateTime time) {
        LocalDateTime now = LocalDateTime.now();
        return now.isAfter(time);
    }

    public static long diff(Date endTime, Date startTime) {
        return endTime.getTime() - startTime.getTime();
    }

    /**
     * 创建指定时间
     *
     * @param year  年
     * @param mouth 月
     * @param day   日
     * @return 指定时间
     */
    public static Date buildTime(int year, int mouth, int day) {
        return buildTime(year, mouth, day, 0, 0, 0);
    }

    /**
     * 创建指定时间
     *
     * @param year   年
     * @param mouth  月
     * @param day    日
     * @param hour   小时
     * @param minute 分钟
     * @param second 秒
     * @return 指定时间
     */
    public static Date buildTime(int year, int mouth, int day,
                                 int hour, int minute, int second) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.MONTH, mouth - 1);
        calendar.set(Calendar.DAY_OF_MONTH, day);
        calendar.set(Calendar.HOUR_OF_DAY, hour);
        calendar.set(Calendar.MINUTE, minute);
        calendar.set(Calendar.SECOND, second);
        calendar.set(Calendar.MILLISECOND, 0); // 一般情况下，都是 0 毫秒
        return calendar.getTime();
    }

    public static Date max(Date a, Date b) {
        if (a == null) {
            return b;
        }
        if (b == null) {
            return a;
        }
        return a.compareTo(b) > 0 ? a : b;
    }

    public static LocalDateTime max(LocalDateTime a, LocalDateTime b) {
        if (a == null) {
            return b;
        }
        if (b == null) {
            return a;
        }
        return a.isAfter(b) ? a : b;
    }

    /**
     * 计算当期时间相差的日期
     *
     * @param field  日历字段.<br/>eg:Calendar.MONTH,Calendar.DAY_OF_MONTH,<br/>Calendar.HOUR_OF_DAY等.
     * @param amount 相差的数值
     * @return 计算后的日志
     */
    public static Date addDate(int field, int amount) {
        return addDate(null, field, amount);
    }

    /**
     * 计算当期时间相差的日期
     *
     * @param date   设置时间
     * @param field  日历字段 例如说，{@link Calendar#DAY_OF_MONTH} 等
     * @param amount 相差的数值
     * @return 计算后的日志
     */
    public static Date addDate(Date date, int field, int amount) {
        if (amount == 0) {
            return date;
        }
        Calendar c = Calendar.getInstance();
        if (date != null) {
            c.setTime(date);
        }
        c.add(field, amount);
        return c.getTime();
    }

    /**
     * 是否今天
     *
     * @param date 日期
     * @return 是否
     */
    public static boolean isToday(LocalDateTime date) {
        return LocalDateTimeUtil.isSameDay(date, LocalDateTime.now());
    }


    /**
     * 本日0时
     *
     * @return
     */
    public static Date getTodayStart() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.HOUR_OF_DAY, 0); // 将小时数设为0
        calendar.set(Calendar.MINUTE, 0); // 将分钟数设为0
        calendar.set(Calendar.SECOND, 0); // 将秒数设为0
        calendar.set(Calendar.MILLISECOND, 0); // 将毫秒数设为0
        return calendar.getTime();
    }

    /**
     * 本日23时
     *
     * @return
     */
    public static Date getTodayEnd() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.HOUR_OF_DAY, 23); // 将小时数设为23
        calendar.set(Calendar.MINUTE, 59); // 将分钟数设为59
        calendar.set(Calendar.SECOND, 59); // 将秒数设为59
        calendar.set(Calendar.MILLISECOND, 999); // 将毫秒数设为999
        return calendar.getTime();
    }

    //    public static LocalDateTime getFirstDayOfMonth() {
//        // 获取当前日期
//        LocalDate currentDate = LocalDate.now();
//
//        // 获取当前月份的第一天
//        LocalDate firstDayOfMonth = currentDate.withDayOfMonth(1);
//
//        // 构造时间为 00:00:00
//        LocalTime startTime = LocalTime.of(0, 0, 0);
//
//        // 组合日期和时间
//        return LocalDateTime.of(firstDayOfMonth, startTime);
//    }
//
//    public static LocalDateTime getLastDayOfMonth() {
//        // 获取当前日期
//        LocalDate currentDate = LocalDate.now();
//
//        // 获取当前月份
//        Month currentMonth = currentDate.getMonth();
//
//        // 获取当前月份的下一个月份
//        Month nextMonth = currentMonth.plus(1);
//
//        // 获取下一个月份的第一天
//        LocalDate firstDayOfNextMonth = LocalDate.of(currentDate.getYear(), nextMonth, 1);
//
//        // 前一天即为当前月份的最后一天
//        LocalDate lastDayOfMonth = firstDayOfNextMonth.minusDays(1);
//
//        // 构造时间为 23:59:59
//        LocalTime endTime = LocalTime.of(23, 59, 59);
//
//        // 组合日期和时间
//        return LocalDateTime.of(lastDayOfMonth, endTime);
//    }
    public static Date getFirstDayOfMonth() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);

        return calendar.getTime();
    }

    public static Date getLastDayOfMonth() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 999);

        return calendar.getTime();
    }


    /**
     * 日期路径 即年/月/日 如20180808
     */
    public static final String dateTime() {
        Date now = new Date();
        return DateFormatUtils.format(now, "yyyyMMdd");
    }


    public static Date getFirstDayOfMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        return calendar.getTime();
    }

    public static Date getLastDayOfMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
        return calendar.getTime();
    }


    /**
     * LocalDateTime 格式的本月第一天
     *
     * @return
     */

    public static LocalDateTime getFirstMonth() {
        // 获取当前的年和月
        LocalDateTime currentDateTime = LocalDateTime.now();
        int year = currentDateTime.getYear();
        Month month = currentDateTime.getMonth();
        // 获取本月的第一天并转换为LocalDateTime格式
        LocalDateTime firstDayOfMonth = LocalDateTime.of(year, month, 1, 0, 0);
        return firstDayOfMonth;
    }

    /**
     * LocalDateTime 格式的本月最后一天
     *
     * @return
     */

    public static LocalDateTime getLastMonth() {
        // 获取当前的年和月
        LocalDateTime currentDateTime = LocalDateTime.now();
        int year = currentDateTime.getYear();
        Month month = currentDateTime.getMonth();
        // 获取本月的最后一天并转换为LocalDateTime格式
        LocalDate lastDay = LocalDate.of(year, month, 1).plusMonths(1).minusDays(1);
        LocalDateTime lastDayOfMonth = LocalDateTime.of(year, month, lastDay.getDayOfMonth(), 23, 59);
        return lastDayOfMonth;
    }

    public static String getDayString() {
        // 获取当前系统时间
        LocalDateTime currentDateTime = LocalDateTime.now();
        // 格式化时间为字符串类型
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); // 定义日期时间格式
        String formattedDateTime = currentDateTime.format(formatter); // 将时间格式化为字符串
        return formattedDateTime;
    }

    public static String getMonthFirstDay() {
        // 获取当月第一天
        LocalDate firstDay = LocalDate.now().with(TemporalAdjusters.firstDayOfMonth());
        // 格式化时间为字符串类型
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); // 定义日期时间格式
        String formattedDateTime = firstDay.format(formatter); // 将时间格式化为字符串
        return formattedDateTime + "00:00:00";
    }

    public static String getMonthLastDay() {
        // 获取当月最后一天
        LocalDate lastDay = LocalDate.now().with(TemporalAdjusters.lastDayOfMonth());
        // 格式化时间为字符串类型
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); // 定义日期时间格式
        String formattedDateTime = lastDay.format(formatter); // 将时间格式化为字符串
        return formattedDateTime + " 23:59:59";
    }

    /**
     * 将日期转换成String
     *
     * @param date
     * @return
     */

    public static String getDataToString(LocalDateTime date) {
        // 格式化时间为字符串类型
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); // 定义日期时间格式
        String formattedDateTime = date.format(formatter); // 将时间格式化为字符串
        return formattedDateTime;
    }

    /**
     * 根据日期返回距离多少时间
     *
     * @param date
     */
    public static String getString(LocalDateTime date) {
        LocalDateTime currentTime = LocalDateTime.now();
        Duration duration = Duration.between(currentTime, date).abs();
        if (duration.toHours() <= 24) {
            return date.format(DateTimeFormatter.ofPattern("HH:mm"));
        } else if (duration.toHours() <= 38) {
            return "昨日" + date.format(DateTimeFormatter.ofPattern("HH:mm"));
        } else if (duration.toHours() <= 48) {
            return date.format(DateTimeFormatter.ofPattern("MM月dd日 HH点"));
        } else {
            return date.format(DateTimeFormatter.ofPattern("yyyy年 MM月 dd日:HH时"));
        }
    }

}
